//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//

/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using EffiProzDB.DataTypes;
using EffiProzDB.Lib;
using EffiProzDB.ScriptIO;


namespace EffiProzDB.RowIO
{
    /**
     *  Class for reading the data for a database row from the script file.
     *
     * @author fredt@users
     * @version 1.8.0
     * @since 1.7.3
     */
    public class RowInputTextLog : RowInputBase
    , RowInputInterface
    {
        Tokenizer tokenizer;
        string tableName = null;
        string schemaName = null;
        int statementType;

        public RowInputTextLog() :  base(new byte[0])
        {          

            tokenizer = new Tokenizer();
        }

        public void setSource(string text)
        {

            tokenizer.reset(text);

            statementType = ScriptReaderBase.ANY_STATEMENT;

            string s = tokenizer.getString();

            if (s.Equals(Token.T_INSERT))
            {
                statementType = ScriptReaderBase.INSERT_STATEMENT;

                tokenizer.getString();

                tableName = tokenizer.getString();

                tokenizer.getString();
            }
            else if (s.Equals(Token.T_DELETE))
            {
                statementType = ScriptReaderBase.DELETE_STATEMENT;

                tokenizer.getString();

                tableName = tokenizer.getString();
            }
            else if (s.Equals(Token.T_COMMIT))
            {
                statementType = ScriptReaderBase.COMMIT_STATEMENT;
            }
            else if (s.Equals(Token.T_SET))
            {
                if (tokenizer.isGetThis(Token.T_SCHEMA))
                {
                    schemaName = tokenizer.getSimpleName();
                    statementType = ScriptReaderBase.SCHEMA_STATEMENT;
                }
            }
        }

        public int getStatementType()
        {
            return statementType;
        }

        public string getTableName()
        {
            return tableName;
        }

        public string getSchemaName()
        {
            return schemaName;
        }

        protected string readField()
        {

            try
            {
                tokenizer.getString();

                if (statementType == ScriptReaderBase.DELETE_STATEMENT)
                {
                    tokenizer.getString();
                    tokenizer.getString();
                }

                string s = tokenizer.getString();

                if (tokenizer.getType() == Types.NULL)
                {
                    s = null;
                }

                return s;
            }
            catch (HsqlException e)
            {
                throw new Exception(e.Message);
            }
        }

        protected string readNumberField()
        {

            try
            {
                tokenizer.getString();

                if (statementType == ScriptReaderBase.DELETE_STATEMENT)
                {
                    tokenizer.getString();
                    tokenizer.getString();
                }

                string s = tokenizer.getString();

                if ("-".Equals(s))
                {
                    s = s + tokenizer.getString();
                }
                else if (tokenizer.getType() == Types.NULL)
                {
                    s = null;
                }

                return s;
            }
            catch (HsqlException e)
            {
                throw new Exception(e.Message);
            }
        }

        public override string readString()
        {

            string s = readField();

            return (s);
        }

        public  short readShortData()
        {

            string s = readNumberField();

            if (s == null)
            {
                return 0;
            }

            return short.Parse(s);
        }

        public override int readIntData()
        {

            string s = readNumberField();

            if (s == null)
            {
                return 0;
            }

            return int.Parse(s);
        }

        public override long readLongData()
        {

            string s = readNumberField();

            if (s == null)
            {
                return 0;
            }

            return long.Parse(s);
        }

        public override int readType()
        {
            return 0;
        }

        protected override bool checkNull()
        {

            // Return null on each column read instead.
            return false;
        }

        protected override string readChar(int type)
        {
            return readString();
        }

        protected override int? readSmallint()
        {

            string s = readNumberField();

            if (s == null)
            {
                return null;
            }

            int i = int.Parse(s);

            return (i);
        }

        protected override int? readInteger()
        {

            string s = readNumberField();

            if (s == null)
            {
                return null;
            }

            int i = int.Parse(s);

            return (i);
        }

        protected override long? readBigint()
        {

            string s = readNumberField();

            if (s == null)
            {
                return null;
            }

            long i = long.Parse(s);

            return (i);
        }

        protected override double? readReal(int type)
        {

            string s = readNumberField();

            if (s == null)
            {
                return null;
            }

            double i = double.Parse(s);

            if (tokenizer.isGetThis(Token.T_DIVIDE))
            {
                s = tokenizer.getString();

                // parse simply to ensure it's a number
                double ii = double.Parse(s);

                if (i == 0E0)
                {
                    i = Double.NaN;
                }
                else if (i == -1E0)
                {
                    i = Double.NegativeInfinity;
                }
                else if (i == 1E0)
                {
                    i = Double.PositiveInfinity;
                }
            }

            return BitConverter.DoubleToInt64Bits(i);
        }

        protected override Decimal? readDecimal()
        {

            string s = readNumberField();

            if (s == null)
            {
                return null;
            }

            Decimal i = Decimal.Parse(s);

            return (i);
        }

        protected override DateTime? readTime()
        {

            string s = readField();

            if (s == null)
            {
                return null;
            }

            return DateTime.Parse(s);
        }

        protected override DateTime? readDate()
        {

            string s = readField();

            if (s == null)
            {
                return null;
            }

            return DateTime.Parse(s);
        }

        protected override DateTime? readTimestamp()
        {

            string s = readField();

            if (s == null)
            {
                return null;
            }

            return DateTime.Parse(s);
        }

        protected override bool? readBit()
        {

            string s = readField();

            if (s == null)
            {
                return null;
            }

            return s.Equals("TRUE",StringComparison.InvariantCultureIgnoreCase) ? true
                                              : false;
        }

        protected override Object readOther()
        {

            byte[] data;
            string s = readField();

            if (s == null)
            {
                return null;
            }

            data = Column.hexToByteArray(s);

            return new DotNetObject(data);
        }

        protected override Binary readBinary(int type)
        {

            string s = readField();

            if (s == null)
            {
                return null;
            }

            return new Binary(Column.hexToByteArray(s), false);
        }
    }
}
